// Copyright (C) joyinter
// All rights reserved.
// 
// Author : Jiang Li
// Date   : 2004-11-19

#include "stdafx.h"
#include "base_timer.h"

namespace JoyServer
{

// class CJoyTimerObject

//##ModelId=44CEFAD10061
CJoyTimerObject::CJoyTimerObject()
{
    m_timer     = NULL;
    m_elapse    = 0;
    m_lastActive= 0;
}

//##ModelId=44CEFAD10062
CJoyTimerObject::~CJoyTimerObject()
{
}

//##ModelId=44CEFAD10071
void CJoyTimerObject::Update()
{
    m_lastActive = GetTickCount()-m_elapse-1;
}

//##ModelId=44CEFAD10064
bool CJoyTimerObject::Create(CJoyTimer* pTimer, DWORD dwElapse)
{
    m_timer     = pTimer;
    m_elapse    = dwElapse;
    m_lastActive= GetTickCount();

    CJoyAutoCS gate(m_timer->m_lock);
    m_timer->m_objects.AddTail(this);

    return true;
}

//##ModelId=44CEFAD1006F
void CJoyTimerObject::Destroy()
{
    if(m_timer == NULL)
    {
        return;
    }

    m_timer->RemoveObject(this);
}

//##ModelId=44CEFAD10070
void CJoyTimerObject::Execute()
{
    OnExecute();
    m_lastActive = GetTickCount();
}

//##ModelId=44CEFAD1005F
void CJoyTimerObject::OnExecute()
{
}

// class CJoyTimer

//##ModelId=44CEFAD1009D
CJoyTimer::CJoyTimer()
{
    m_hEvent    = NULL;
    m_tick      = 0;
}

//##ModelId=44CEFAD1009E
CJoyTimer::~CJoyTimer()
{
}

//##ModelId=44CEFAD100A0
bool CJoyTimer::Create(DWORD dwTick)
{
    m_tick      = dwTick;
    m_hEvent    = CreateEvent(NULL, TRUE, FALSE, NULL);
    if(m_hEvent == NULL)
    {
        return false;
    }

    if(!__super::Create())
    {
        return false;
    }
    return true;
}

//##ModelId=44CEFAD100A2
void CJoyTimer::Destroy()
{
	
    ASSERT(m_objects.IsEmpty());

    if(m_hEvent != NULL)
    {
        SetEvent(m_hEvent);
        __super::Destroy();
        CloseHandle(m_hEvent);
        m_hEvent = NULL;
    }
}

//##ModelId=44CEFAD10091
void CJoyTimer::TrackObjects()
{
    CJoyAutoCS gate(m_lock);

    DWORD tick = GetTickCount();
    POSITION pos = m_objects.GetHeadPosition();
    while(pos != NULL)
    {
        CJoyTimerObject* obj = m_objects.GetNext(pos);
        if(tick-obj->m_lastActive > obj->m_elapse)
        {
            obj->OnExecute();
            tick = GetTickCount();
            obj->m_lastActive = tick;
        }
    }
}

//##ModelId=44CEFAD10092
DWORD CJoyTimer::ThreadProc()
{
    while(WAIT_TIMEOUT == WaitForSingleObject(m_hEvent, m_tick))
    {
        TrackObjects();
    }
    return 0;
}

//##ModelId=44CEFAD100A3
void CJoyTimer::AddObject(CJoyTimerObject* pObj)
{
    CJoyAutoCS gate(m_lock);

    ASSERT(pObj->m_timer == NULL);

    m_objects.AddTail(pObj);
    pObj->m_timer = this;
    pObj->m_lastActive  = GetTickCount();
}

//##ModelId=44CEFAD100AB
void CJoyTimer::RemoveObject(CJoyTimerObject* pObj)
{
    CJoyAutoCS gate(m_lock);

    POSITION pos = m_objects.GetHeadPosition();
    while(pos != NULL)
    {
        POSITION tempPos = pos;
        if(pObj == m_objects.GetNext(pos))
        {
            m_objects.RemoveAt(tempPos);
            pObj->m_timer = NULL;
            break;
        }
    }
}

} // namespace JoyServer
